package tcln.gxtx.client.widget.treegrid;

import java.util.List;

import tcln.gxtx.client.utils.collection.GwtCollectionUtils;

import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.store.TreeStoreEvent;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGrid;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel.Joint;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

/**
 * @param <M>
 *            the model type
 * @author Truong Chau Lien Ngoc (lienngoc@gmail.com)
 */
public class ExtendedTreeGrid<M extends ModelData> extends TreeGrid<M> implements TreeGridExtension<M> {

    /**
     * A flag indicating that the icon styles for opening/closing/leaf nodes should NOT be rendered.
     */
    private boolean nodeIconStyleHidden;

    /**
     * @param store
     * @param cm
     */
    public ExtendedTreeGrid(TreeStore<M> store, ColumnModel cm) {
        super(store, cm);
    }

    /**
     * {@inheritDoc}
     */
    public void setNodeIconStyleHidden(boolean nodeIconStyleHidden) {
        this.nodeIconStyleHidden = nodeIconStyleHidden;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Joint calcualteJoint(final M model) {
        return super.calcualteJoint(model);
    };

    /**
     * {@inheritDoc}
     */
    @Override
    public AbstractImagePrototype calculateIconStyle(final M model) {
        if (nodeIconStyleHidden) {
            return null;
        }
        return super.calculateIconStyle(model);
    };
    

    /**
     * Searches for a tree node ID (generated on adding nodes).
     * 
     * @param m
     * @return
     */
    public String findNodeId(final M m) {
        if (m == null) {
            return null;
        } else if (treeStore.getKeyProvider() != null) {
            return generateModelId(m);
        } else {
            return cache.get(m);
        }
    };

    /**
     * {@inheritDoc}
     */
    @Override
    public TreeNode findNode(M m) {
        return super.findNode(m);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onDataChanged(TreeStoreEvent<M> se) {
        super.onDataChanged(se);
        statefulExpandAll(this, treeStore);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onAfterRenderView() {
        super.onAfterRenderView();
        statefulExpandAll(this, treeStore);
    }

    // HACK GXT 2.1.1: because method 'statefulExpand' only handles root items, lower nodes cannot be expanded -> go
    // thorough all items and expand it.
    // TODO LNT [Jun 16, 2010]: review to remove this hack on GXT 2.1.2 (or later).
    @SuppressWarnings("unchecked")
    static <M extends ModelData> void statefulExpandAll(TreeGrid<M> treegrid, TreeStore<M> treeStore) {
        if (treegrid.isStateful() && treeStore.getKeyProvider() != null) {
            List<String> expandedModelIds = (List) treegrid.getState().get("expanded");
            if (!GwtCollectionUtils.isEmpty(expandedModelIds)) {
                for (M child : treeStore.getAllItems()) {
                    String id = treeStore.getKeyProvider().getKey(child);
                    if (expandedModelIds.contains(id)) {
                        treegrid.setExpanded(child, true);
                    }
                }
            }
        }
    }
}
